package com.touni.lambda.diycollectors;

import java.util.*;
import java.util.function.BiConsumer;
import java.util.function.BinaryOperator;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collector;

import static java.util.stream.Collector.Characteristics.IDENTITY_FINISH;
import static java.util.stream.Collector.Characteristics.UNORDERED;

/**
 * @ClassName : ToListCollector
 * @Description :自定义收集器
 * @Author : lwq
 * @Date: 2020-11-21 16:15
 */
//T 流中元素的类型、A 用于累积部分结果的对象类型，R 以及collect操作最终结果的类型。
public class ToSetCollector<T> implements Collector<T, Set<T>, Set<T>> {

    //建立新的结果容器：
    @Override
    public Supplier<Set<T>> supplier() {
        return HashSet::new;
    }

    //将目前的元素放入到结果容器
    @Override  //保存结果的容器  现在的元素
    public BiConsumer<Set<T>, T> accumulator() {
        //return (list,item) -> list.add(item);以下方式更加简洁
        return Set::add;
    }

    //对结果容器应用最终转换
    // 在遍历完流后，finisher方法必须返回在累积过程的最后要调用的一个函数，以便将累加
    //器对象转换为整个集合操作的最终结果。
    @Override
    public Function<Set<T>, Set<T>> finisher() {
        return Function.identity();
    }

    // ========以上三个足以完成对流的顺序规约

    //合并两个结果容器   可对流进行并行规约
    //会返回一个供归约操作使用的函数，它定义了对
    //流的各个子部分进行并行处理时，各个子部分归约所得的累加器要如何合并。
    @Override
    public BinaryOperator<Set<T>> combiner() {
        return (set1,set2) -> {
            set1.addAll(set2);
            return set1;
        };
    }

    //   characteristics会返回一个不可变的Characteristics集合，它定义了收集器的行为
    // Characteristics是一个包含三个项目的枚举。
    //  UNORDERED——归约结果不受流中项目的遍历和累积顺序的影响。
    //  CONCURRENT——accumulator函数可以从多个线程同时调用，且该收集器可以并行归
    //    约流。如果收集器没有标为UNORDERED，那它仅在用于无序数据源时才可以并行归约。
    //  IDENTITY_FINISH——这表明完成器方法返回的函数是一个恒等函数，可以跳过。这种
    //    情况下，累加器对象将会直接用作归约过程的最终结果。这也意味着，将累加器A不加检
    //    查地转换为结果R是安全的
    @Override
    public Set<Characteristics> characteristics() {
        return Collections.unmodifiableSet(EnumSet.of(IDENTITY_FINISH,UNORDERED));
    }
}
